package com.ld.shieldsb.common.core.encryptor;

import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ld.shieldsb.common.core.reflect.ClassUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 一、什么是异或加密？
 * <p>
 * 异或运算中，如果某个字符（或数值）x 与 一个数值m 进行异或运算得到y，则再用y 与 m 进行异或运算就可以还原为 x ， 因此应用这个原理可以实现数据的加密解密功能。
 * <p>
 * 二、异或运算使用场景？
 * <p>
 * 两个变量的互换（不借助第三个变量）
 * <p>
 * 数据的简单加密解密
 * 
 * @ClassName EorEncryptor
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2019年8月5日 上午9:02:23
 *
 */
@Slf4j
public class EorEncryptor implements Encryptor {

    private int orKey = 0x520;
    private static final Pattern p = Pattern.compile("\\s*|t*|r*|n*");

    /**
     * 固定key的方式,
     * <p>
     * 这种方式加密解密 算法一样
     *
     * @param bytes
     * @return
     *//*
       public byte[] encrypt(byte[] bytes) {
       if (bytes == null) {
       return null;
       }
       int len = bytes.length;
       int key = orKey;
       // int key = 0x12;
       for (int i = 0; i < len; i++) {
       bytes[i] ^= key;
       }
       return bytes;
       }*/

    /**
     * 加密
     * <p>
     * 加密实现
     *
     * @param bytes
     * @return
     */
    public static String encode(String value, int key) {
        if (value == null) {
            return null;
        }
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
        int len = bytes.length;
        // int key = 0x12;
        for (int i = 0; i < len; i++) {
            bytes[i] = (byte) (bytes[i] ^ key);
            key = bytes[i];
        }
        return EncodeUtils.encodeHex(bytes);
    }

    /**
     * 解密
     * 
     * @Title decrypt
     * @author 吕凯
     * @date 2019年8月5日 上午9:18:26
     * @param value
     * @param key
     * @return String
     */
    public static String decode(String value, int key) {
        try {
            byte[] bytes = EncodeUtils.decodeHex(value);
            if (bytes == null) {
                return null;
            }
            int len = bytes.length;
            for (int i = len - 1; i > 0; i--) {
                bytes[i] = (byte) (bytes[i] ^ bytes[i - 1]);
            }
            bytes[0] = (byte) (bytes[0] ^ key);
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("", e);
            throw e;
        }
    }

    @Override
    public String encrypt(String value) {
        return encode(value, orKey);
    }

    @Override
    public String decrypt(String value) {
        return decode(value, orKey);
    }

    @Override
    public void setKey(String key) {
        int keyInt = ClassUtil.obj2int(key);
        if (keyInt != 0) {
            orKey = keyInt;
        }
    }

    @Override
    public boolean match(String plaintext, String hashed, String salt) throws Exception {
        if (plaintext == null || hashed == null) {
            return false;
        }
        return decrypt(hashed).equals(plaintext);
    }

    /**
     * 判断字符是否是中文
     *
     * @param c
     *            字符
     * @return 是否是中文
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
    }

    /**
     * 判断字符串是否是乱码
     *
     * @param strName
     *            字符串
     * @return 是否是乱码
     */

    public static boolean isMessyCode(String strName) {
        Matcher m = p.matcher(strName);
        String after = m.replaceAll("");
        String temp = after.replaceAll("\\p{P}", "");
        char[] ch = temp.trim().toCharArray();
        float chLength = ch.length;
        float count = 0;
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (!Character.isLetterOrDigit(c) && !isChinese(c)) {
                count = count + 1;
            }
        }
        float result = count / chLength;
        return result > 0.4;

    }

    /**
     * 包含乱码
     * 
     * @Title hasValidChar
     * @author 吕凯
     * @date 2019年8月22日 上午10:57:05
     * @param str
     * @return boolean
     */
    public static boolean hasValidChar(String str) {
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            // 当从Unicode编码向某个字符集转换时，如果在该字符集中没有对应的编码，则得到0x3f（即问号字符?）
            // 从其他字符集向Unicode编码转换时，如果这个二进制数在该字符集中没有标识任何的字符，则得到的结果是0xfffd
            if ((int) c == 0xfffd) {
                // 存在乱码
                return true;
            }
        }
        return false;
    }

}
